package com.wl.common.system.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.wl.common.core.web.dto.DataStoreDTO;
import com.wl.common.mybatis.utils.PageUtils;
import com.wl.common.system.dao.SysRoleResourceMapper;
import com.wl.common.system.domain.SysRoleResource;
import com.wl.common.system.service.SysRoleResourceService;
import com.wl.common.system.support.dto.SysRoleResourceDTO;
import com.wl.common.system.support.dto.query.SysRoleResourceQueryDTO;
import com.wl.common.system.support.vo.SysRoleResourceVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 后台角色资源关系表 服务实现类
 *
 * @author wanglin
 * @since 2023-09-18
 */
@Service
public class SysRoleResourceServiceImpl implements SysRoleResourceService {

    @Autowired
    private SysRoleResourceMapper sysRoleResourceMapper;

    @Transactional(readOnly = true)
    @Override
    public DataStoreDTO<SysRoleResourceVO> page(Pageable pageable, SysRoleResourceQueryDTO queryDto) {
        QueryWrapper<SysRoleResource> queryWrapper = this.buildQuery(queryDto);
        Page<SysRoleResource> page = PageUtils.transferPage(pageable);
        Page<SysRoleResource> result = this.sysRoleResourceMapper.selectPage(page, queryWrapper);
        return new DataStoreDTO(result.getTotal(), this.transferVo(result.getRecords()));
    }

    @Transactional(readOnly = true)
    @Override
    public List<SysRoleResourceVO> list(Sort sort, SysRoleResourceQueryDTO queryDto) {
        QueryWrapper<SysRoleResource> queryWrapper = this.buildQuery(queryDto);
        PageUtils.transferSort(queryWrapper, sort);
        return this.transferVo(this.sysRoleResourceMapper.selectList(queryWrapper));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void save(SysRoleResourceDTO dto) {
        // TODO 唯一性字段校验
        dto.setId(null);
        sysRoleResourceMapper.insert(this.transferEntity(null, dto));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void update(SysRoleResourceDTO dto) {
        Assert.hasText(dto.getId(), "id不能为空");
        // TODO 唯一性字段校验
        SysRoleResource entity = sysRoleResourceMapper.selectById(dto.getId());
        Assert.notNull(entity, "找不到id为 " + dto.getId() + " 的记录");
        sysRoleResourceMapper.updateById(this.transferEntity(entity, dto));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(Set<String> ids) {
        if (CollectionUtils.isNotEmpty(ids)) {
            sysRoleResourceMapper.deleteBatchIds(ids);
        }
    }

    @Transactional(readOnly = true)
    @Override
    public SysRoleResourceVO get(String id) {
        Assert.hasText(id, "id不能为空");
        SysRoleResource entity = sysRoleResourceMapper.selectById(id);
        Assert.notNull(entity, "找不到id为 " + id + " 的记录");
        return this.transferVo(entity);
    }

    @Transactional(readOnly = true)
    @Override
    public List<SysRoleResource> getListByRoleIds(Set<String> roleIds) {
        if (CollectionUtils.isEmpty(roleIds)) {
            return Lists.newArrayList();
        }
        QueryWrapper<SysRoleResource> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().in(SysRoleResource::getRoleId, roleIds);
        return sysRoleResourceMapper.selectList(queryWrapper);
    }

    @Transactional(readOnly = true)
    @Override
    public List<SysRoleResource> getListByRoleId(String roleId) {
        if (StringUtils.isBlank(roleId)) {
            return Lists.newArrayList();
        }
        QueryWrapper<SysRoleResource> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(SysRoleResource::getRoleId, roleId);
        return sysRoleResourceMapper.selectList(queryWrapper);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addResourceListByRoleId(String roleId, List<String> resourceIdList) {
        if (org.springframework.util.CollectionUtils.isEmpty(resourceIdList)) {
            return;
        }
        resourceIdList.stream().forEach(e -> {
            SysRoleResource roleResource = new SysRoleResource(roleId, e);
            sysRoleResourceMapper.insert(roleResource);
        });
    }

    private QueryWrapper<SysRoleResource> buildQuery(SysRoleResourceQueryDTO queryDto) {
        QueryWrapper<SysRoleResource> queryWrapper = new QueryWrapper<>();
        if (Objects.nonNull(queryDto)) {
            queryWrapper.lambda().eq(StringUtils.isNotBlank(queryDto.getId()), SysRoleResource::getId, queryDto.getId());
        }
        return queryWrapper;
    }

    private SysRoleResource transferEntity(SysRoleResource entity, SysRoleResourceDTO dto) {
        if (Objects.isNull(entity)) {
            entity = new SysRoleResource();
        }
        BeanUtils.copyProperties(dto, entity);
        return entity;
    }

    private List<SysRoleResourceVO> transferVo(List<SysRoleResource> entities) {
        if (CollectionUtils.isEmpty(entities)) {
            return Lists.newArrayList();
        }

        List<SysRoleResourceVO> voList = entities.stream().map(entity -> {
            SysRoleResourceVO vo = new SysRoleResourceVO();
            BeanUtils.copyProperties(entity, vo);
            return vo;
        }).collect(Collectors.toList());
        return voList;
    }

    private SysRoleResourceVO transferVo(SysRoleResource entity) {
        if (Objects.isNull(entity)) {
            return null;
        }
        SysRoleResourceVO vo = new SysRoleResourceVO();
        BeanUtils.copyProperties(entity, vo);
        return vo;
    }
}
